在過去的幾天我們讓 YOLO 學會了在我們的 Sentinel-2 衛星圖畫預測框,但是有一個問題,當我們打開推理預測的文字檔會發現模型只給我們 [120,350,480,600] 這種資訊,但這只是一組 像素座標 (Pixel Coordinates) ,對於一班電腦視覺專案可能只到這裡就結束了,但對於遙測專案可能不是,我們還有需要解決的問題,那就是目標物的絕對位置在哪?
在說明座標轉換之前我們有兩個必須知道的系統運作方式:
原點位於圖片的左上角,單位為像素(Pixel)。X 軸向右遞增,Y 軸向下遞增,與一般數學座標系相反。
原點取決於不同的地圖投影法,單位為 度 (經緯度)、公尺 (投影網格),X 軸向右遞增,Y 軸向上遞增。
我們可以這樣想,YOLO 輸出的是一張目標物影像,但那張上面除了目標物以外都是透明的,我們要做的就是把這張有目標物的影像與 Google Maps 做結合。
在疊圖過程中我們需要思考以下幾件事:
1.照片的角要對其哪裡 (定位)
2.照片要放大或縮小 (比例尺)
3.照片有沒有歪斜 (旋轉)
帶有地理資訊的衛星圖 (GeoTIFF格式) 裡面其實已經有 Metadata (元數據),裡面包含 6 個轉換參數(a,b,c,d,e,f)。
可以透過線性代數中的 仿射變換 (Affine Transform) 公式,我們就可以把 YOLO 給的影像與真實地圖融合。
這是在照片左上角(第一個像素)在真實地圖中的絕對經緯度 (或公尺座標)。
他可以說是把影響與真實地圖釘在一起,只要這個基準點存在在 GPS地圖上,後面的像素就可以有參考的依據。
判斷影像中的像素在真實世界有多寬或是多長。
以 Sentinel-2 衛星圖來說,一個像素在真實世界中的 10m,那麼 a 大概就是 10。
這裡有個有趣的點,為甚麼 e 常常會是負數,你在看電腦螢幕時,滑鼠越往下滑,Y 軸的像素數字會越來越大,但在真實世界的地圖上越往下走緯度座標應該要越來越小,為了把往下遞增的螢幕對齊往下遞減的地球,這代表 Y 軸比例尺的 e 必須乘上負號來反轉方向。
透過衛星拍攝的影像不一定每次都對準正北極,這會導致拍出來的照片有點歪歪的。
這兩個參數的作用是告訴你這個有像偏移了多少度,如果衛星圖在下載前就已經透過正射校正處理過,確保正北朝上,那這兩個參數通常會是 0,代表不需要做額外的旋轉。
我們算出地理座標之後還是必須透過 EPSG 代碼 來定義這個座標是哪種地圖標準。
以 公尺 為單位的投影坐標系,使合用來計算大單位的目標物。
以 度 為單位的經緯度系統,是 Google Maps 和 GPS 使用的通用標準。
在 Pyhton 中我們不用寫複雜的矩陣,Rasterio 已經都幫我們封裝好了:
import rasterio
# 讀取帶有地理資訊的衛星圖
with rasterio.open("sentinel2_taiwan.tif") as src:
# 提取該圖片專屬的 Affine 轉換矩陣
transform_matrix = src.transform
# 假設這是 YOLO 抓到的目標物中心點像素
pixel_x, pixel_y = 120, 350
# rasterio 覆寫了乘號,底層自動完成 Affine 運算
geo_x, geo_y = transform_matrix * (pixel_x, pixel_y)
print(({geo_x}, {geo_y}))
明天預計會將這個結合 YOLO 的推論腳本,那我們明天見。